#include "CrubeDemo.h"
#include<vector>
#include "RenderManager.h"
#include "Camera.h"

struct VertexStruct
{
	XMFLOAT4 pos;
	XMFLOAT4 Corlor;
};

struct ConstCubeBuffer
{
	XMMATRIX m_world;
	XMMATRIX m_view;
	XMMATRIX m_proj;
	XMFLOAT4 m_Corlor;
};

CrubeDemo::CrubeDemo():m_pInputLayout(nullptr), m_pVertexBuffer(nullptr), m_pSolidColorPS(nullptr), m_pSolidColorVS(nullptr), g_pConstantBuffer11(nullptr)
{
}


CrubeDemo::~CrubeDemo()
{
}

bool CrubeDemo::LoadContent()
{
	ID3DBlob *vsBuffer = 0;
	bool compileResult = CompileD3DShader(L"ShaderCrube.fx", "VS_Main", "vs_4_0", &vsBuffer);
	if (!compileResult)
	{
		MessageBoxA(0, "载入顶点着色器错误", "编译错误", MB_OK);
		return false;
	}

	HRESULT result;
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateVertexShader(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(),
		0, &m_pSolidColorVS);

	if (FAILED(result))
	{
		if (vsBuffer)
		{
			vsBuffer->Release();
		}
		return false;
	}

	D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
	{
		{ "POSITION",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 },
		{ "COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,16,D3D11_INPUT_PER_VERTEX_DATA,0 },
	};

	UINT numLayoutElements = ARRAYSIZE(solidColorLayout);
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateInputLayout(solidColorLayout, numLayoutElements, vsBuffer->GetBufferPointer(),
		vsBuffer->GetBufferSize(), &m_pInputLayout);
	vsBuffer->Release();

	if (FAILED(result))
	{
		return false;
	}

	//载入像素着色器
	ID3DBlob *psBuffer = 0;
	compileResult = CompileD3DShader(L"ShaderCrube.fx", "PSSolid", "ps_4_0", &psBuffer);
	if (!compileResult)
	{
		MessageBoxA(0, "像素着色器加载失败", "编译错误", MB_OK);
		return false;
	}

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(),
		0, &m_pSolidColorPS);
	psBuffer->Release();
	if (FAILED(result))
	{
		return false;
	}

	//构造顶点
	VertexStruct Vertex[] =
	{
		{ XMFLOAT4(-1.f,1.f,-1.f,1.f),XMFLOAT4(0.f,0.f,1.f,1.f)},
		{ XMFLOAT4(1.f,1.f,-1.f,1.f),XMFLOAT4(0.f,1.f,0.f,1.f)},
		{ XMFLOAT4(1.f,-1.f,-1.f,1.f),XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
		{ XMFLOAT4(-1.f,-1.f,-1.f,1.f),XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
		{ XMFLOAT4(-1.f,-1.f,1.f,1.f),XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT4(-1.f,1.f,1.f,1.f),XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
		{ XMFLOAT4(1.f,1.f,1.f,1.f),XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
		{ XMFLOAT4(1.f,-1.f,1.f,1.f),XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
	};

	std::vector<VertexStruct> VertexList;
	for (int i = 0; i < 8; i++)
	{
		VertexList.push_back(Vertex[i]);
	}

	D3D11_BUFFER_DESC vertexDesc;
	ZeroMemory(&vertexDesc, sizeof(vertexDesc));
	vertexDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexDesc.ByteWidth = sizeof(VertexStruct) * VertexList.size();

	D3D11_SUBRESOURCE_DATA resourceData;
	ZeroMemory(&resourceData, sizeof(resourceData));
	resourceData.pSysMem = VertexList.data();

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateBuffer(&vertexDesc, &resourceData, &m_pVertexBuffer);
	if (FAILED(result))
	{
		return false;
	}

	//构造Indexbuffer
	WORD indices[] =
	{
       0,1,2,
	   0,2,3,

	   1,6,7,
	   1,7,2,

	   5,0,3,
	   5,3,4,

	   6,5,4,
	   6,4,7,

	   5,6,1,
	   5,1,0,

	   3,2,4,
	   2,7,4
	};

	D3D11_BUFFER_DESC vertexIndexDesc;
	ZeroMemory(&vertexIndexDesc, sizeof(vertexIndexDesc));
	vertexIndexDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexIndexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	vertexIndexDesc.ByteWidth = sizeof(WORD) * 36;
	vertexIndexDesc.CPUAccessFlags = 0;

	D3D11_SUBRESOURCE_DATA IndexData;
	ZeroMemory(&IndexData, sizeof(IndexData));
	IndexData.pSysMem = indices;
	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateBuffer(&vertexIndexDesc, &IndexData, &m_pIndexBuffer);
	if (FAILED(result))
	{
		return false;
	}

	//Const Buffer

	D3D11_BUFFER_DESC cbDesc;
	ZeroMemory(&cbDesc, sizeof(D3D11_BUFFER_DESC));
	cbDesc.ByteWidth = sizeof(ConstCubeBuffer);
	cbDesc.Usage = D3D11_USAGE_DEFAULT;
	cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	cbDesc.CPUAccessFlags = 0;

	// Fill in the subresource data.
	//D3D11_SUBRESOURCE_DATA InitData;
	//InitData.pSysMem = &ConstBufferData;
	//InitData.SysMemPitch = 0;
	//InitData.SysMemSlicePitch = 0;

	result = RenderManager::GetRenderManagerInstance()->GetD3DDeviece()->CreateBuffer(&cbDesc, nullptr,
		&g_pConstantBuffer11);
	if (FAILED(result))
	{
		MessageBoxA(0, 0, 0, 0);
		return false;
	}


	//构建矩阵
	XMFLOAT4 TransFrom(0.f, 0.f, 0.f, 1.f);
	TransFrom.x = Pos.x;
	TransFrom.y = Pos.y;
	TransFrom.z = Pos.z;
	g_CubeWorld = XMMatrixRotationX(Rotation.x / 180 * XM_PI)*XMMatrixRotationY(Rotation.y / 180 * XM_PI)*XMMatrixRotationY(Rotation.z / 180 * XM_PI)
		*XMMatrixTranslationFromVector(XMLoadFloat4(&TransFrom));

	return true;
}

void CrubeDemo::UnLoadContent()
{
	if (m_pSolidColorPS)
		m_pSolidColorPS->Release();
	if (m_pSolidColorVS)
		m_pSolidColorVS->Release();
	if (m_pVertexBuffer)
		m_pVertexBuffer->Release();
	if (m_pInputLayout)
		m_pInputLayout->Release();
	if (g_pConstantBuffer11)
		g_pConstantBuffer11->Release();
	if (m_pIndexBuffer)
		m_pIndexBuffer->Release();

	m_pSolidColorVS = 0;
	m_pSolidColorPS = 0;
	m_pVertexBuffer = 0;
	m_pInputLayout = 0;
	m_pIndexBuffer = nullptr;
	g_pConstantBuffer11 = nullptr;
}

void CrubeDemo::Update(float dt)
{
	static float t = 0.0f;
	static ULONGLONG timeStart = 0;
	ULONGLONG timeCur = GetTickCount64();
	if (timeStart == 0)
		timeStart = timeCur;
	t = (timeCur - timeStart) / 1000.f;
	Rotation.y += 0.01;
	XMFLOAT4 TransFrom(0.f, 0.f, 0.f, 1.f);
	TransFrom.x = Pos.x;
	TransFrom.y = Pos.y;
	TransFrom.z = Pos.z;
	g_CubeWorld = XMMatrixRotationX(Rotation.x / 180 * XM_PI)*XMMatrixRotationY(Rotation.y / 180 * XM_PI)*XMMatrixRotationY(Rotation.z / 180 * XM_PI)
		*XMMatrixTranslationFromVector(XMLoadFloat4(&TransFrom));
}

void CrubeDemo::Render()
{

	if (RenderManager::GetRenderManagerInstance()->GetImmediateContext() == 0)
		return;
	if (TheCamera == nullptr)
	{
		return;
	}
	RenderManager::GetRenderManagerInstance()->SetNoCull(true);

	UINT stride = sizeof(VertexStruct);
	UINT offset = 0;
	//设置数据信息格式控制信息
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetInputLayout(m_pInputLayout);
	//设置要绘制的几何体信息
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);

	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
	//指明如何绘制三角形
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->VSSetConstantBuffers(0, 1, &g_pConstantBuffer11);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->PSSetConstantBuffers(0, 1, &g_pConstantBuffer11);

	ConstCubeBuffer ConstBufferData;
	ConstBufferData.m_world = XMMatrixTranspose(g_CubeWorld);
	if (TheCamera)
	{
		ConstBufferData.m_view = XMMatrixTranspose(TheCamera->GetView());
		ConstBufferData.m_proj = XMMatrixTranspose(TheCamera->GetProj());
	}
	XMFLOAT4 Colorlist[] =
	{
		XMFLOAT4(1.0f, 0.f, 0.0f, 1.0f),
		XMFLOAT4(0.0f, 1.f, 0.0f, 1.0f),
		XMFLOAT4(0.0f, 0.f, 1.0f, 1.0f),
		XMFLOAT4(0.0f, 1.f, 1.0f, 1.0f),
		XMFLOAT4(1.0f, 0.f, 1.0f, 1.0f),
		XMFLOAT4(1.0f, 1.f, 0.0f, 1.0f),

	};
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->VSSetShader(m_pSolidColorVS, 0, 0);
	RenderManager::GetRenderManagerInstance()->GetImmediateContext()->PSSetShader(m_pSolidColorPS, 0, 0);
	for (int i = 0; i < 6; i++)
	{
		ConstBufferData.m_Corlor = Colorlist[i];

		RenderManager::GetRenderManagerInstance()->GetImmediateContext()->UpdateSubresource(
			g_pConstantBuffer11,
			0,
			nullptr,
			&ConstBufferData,
			0,
			0
			);
		RenderManager::GetRenderManagerInstance()->GetImmediateContext()->DrawIndexed(6, 6 * i, 0);

	}
}
